﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Syndication;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Xml;
using System.Xml.Linq;
using EDXLHistory;
using ICNETServices;
using Microsoft.ServiceModel.Web;
using EDXLSharp;

namespace ICNETREST
{
  /// <summary>
  /// HistoryService provides access to the EDXL History data, available URLS are:
  /// Received/All
  /// Received/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}
  /// Received/Time?Start={DTStart}&End={DTEnd}
  /// Received/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}
  /// 
  /// DEXML/All
  /// DEXML/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}
  /// DEXML/Time?Start={DTStart}&End={DTEnd}
  /// DEXML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}
  /// 
  /// KML/All
  /// KML/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}
  /// KML/Time?Start={DTStart}&End={DTEnd}
  /// KML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}
  /// 
  /// GeoRSS/All
  /// GeoRSS/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}
  /// GeoRSS/Time?Start={DTStart}&End={DTEnd}
  /// 
  /// Playback/KML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}
  /// Playback/KML/Type?Start={DTStart}&End={DTEnd}&Type={UnitType}
  /// </summary>
  [ServiceContract(Namespace = "urn:icnet:mitre:org:HistoryService")]
  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
  public class HistoryService
  {
    /// <summary>
    /// Endpoint to return all of the entries in the Received history table
    /// </summary>
    /// <returns>XML representation of Received history table entries</returns>
    [WebGet(UriTemplate = "Received/All", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetReceivedAll()
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("ReceivedItems");
      List<XElement> items = History.GetReceivedAll();
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return entries in the Received history table that match on 
    /// Distribution Id, Sender Id, and/or DE DateTime Sent
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTSent">DateTime Sent</param>
    /// <returns>XML representation of Received history table entries</returns>
    [WebGet(UriTemplate = "Received/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetReceived(string IdStr, string Sender, string DTSent)
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("ReceivedItems");
      List<XElement> items = History.GetReceivedByDE(IdStr, Sender, DTSent);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return entries in the Received history table that match on 
    /// time range
    /// </summary>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>XML representation of Received history table entries</returns>
    [WebGet(UriTemplate = "Received/Time?Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetReceivedByTime(string DTStart, string DTEnd)
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("ReceivedItems");
      List<XElement> items = History.GetReceivedByTime(DTStart, DTEnd);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return entries in the Received history table that match on 
    /// Distribution Id, Sender Id, and/or time range
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>XML representation of Received history table entries</returns>
    [WebGet(UriTemplate = "Received/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetReceivedByDEAndTime(string IdStr, string Sender, string DTStart, string DTEnd)
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("ReceivedItems");
      List<XElement> items = History.GetReceivedByDEAndTime(IdStr, Sender, DTStart, DTEnd);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return XML of all of the DE messages in the Message history table
    /// </summary>
    /// <returns>XML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "DEXML/All", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetDEAll()
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("DistributionElements");
      List<XElement> items = History.GetAllDE();
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return XML of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or DE DateTime Sent
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTSent">DateTime Sent</param>
    /// <returns>XML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "DEXML/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetDE(string IdStr, string Sender, string DTSent="")
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("DistributionElements");
      List<XElement> items = History.GetDE(IdStr, Sender, DTSent);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return XML of the DE messages in the Message history table that match on 
    /// time range
    /// </summary>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>XML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "DEXML/Time?Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetDEByTime(string DTStart, string DTEnd)
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("DistributionElements");
      List<XElement> items = History.GetDEByTime(DTStart, DTEnd);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return XML of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or time range
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>XML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "DEXML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetDEByDEAndTime(string IdStr, string Sender, string DTStart, string DTEnd)
    {
      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("DistributionElements");
      List<XElement> items = History.GetDEByDEAndTime(IdStr, Sender, DTStart, DTEnd);
      foreach (XElement item in items)
      {
        item.WriteTo(xmlWriter);
      }

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();
      WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return KML of all of the DE messages in the Message history table
    /// </summary>
    /// <returns>KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "KML/All", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetKMLFeedAll()
    {
      List<XElement> items = null;
      items = History.GetAllDE();

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");
      xmlWriter.WriteElementString("name", "EDXL History KML Feed");

      History.GetKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return KML of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or DE DateTime Sent
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTSent">DateTime Sent</param>
    /// <returns>KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "KML/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetKMLFeedByDE(string IdStr, string Sender, string DTSent = "")
    {
      List<XElement> items = null;
      items = History.GetDE(IdStr, Sender, DTSent);

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");
      xmlWriter.WriteElementString("name", "EDXL History KML Feed");

      History.GetKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return KML of the DE messages in the Message history table that match on 
    /// time range
    /// </summary>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "KML/Time?Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetKMLFeedByTime(string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByTime(DTStart, DTEnd);

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");
      xmlWriter.WriteElementString("name", "IC.NET History KML Feed");

      History.GetKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return KML of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or time range
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "KML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetKMLFeedByDEAndTime(string IdStr, string Sender, string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByDEAndTime(IdStr, Sender, DTStart, DTEnd);

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");
      xmlWriter.WriteElementString("name", "IC.NET History KML Feed");

      History.GetKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return a playback version of KML of the DE messages in the Message history table that match on 
    /// unit type and/or time range
    /// </summary>
    /// <param name="UnitType">Unit TYpe</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>Playback KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "Playback/KML/UnitType?Type={UnitType}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetPlaybackKMLFeedByType(string UnitType, string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByUnitTypeAndTime(UnitType, DTStart, DTEnd);

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");

      string sName = "All";

      if (!string.IsNullOrWhiteSpace(DTStart))
      {
        sName = DTStart;

        if (!string.IsNullOrWhiteSpace(DTEnd))
        {
          sName = sName + " - " + DTEnd;
        }
      }
      else if (!string.IsNullOrWhiteSpace(DTEnd))
      {
        sName = DTEnd;
      }
      else if (!string.IsNullOrWhiteSpace(UnitType))
      {
        sName = "UnitType: " + UnitType;
      }

      xmlWriter.WriteElementString("name", sName);

      History.GetPlaybackKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return a playback version of KML of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or time range
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>Playback KML representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "Playback/KML/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public XElement GetPlaybackKMLFeedByDEAndTime(string IdStr, string Sender, string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByDEAndTime(IdStr, Sender, DTStart, DTEnd);

      StringBuilder sb = new StringBuilder();
      XmlWriter xmlWriter = XmlWriter.Create(sb);
      xmlWriter.WriteStartDocument(false);
      xmlWriter.WriteStartElement("kml", "http://earth.google.com/kml/2.0");
      xmlWriter.WriteAttributeString("xmlns", "atom", null, "http://www.w3.org/2005/Atom");
      xmlWriter.WriteStartElement("Document");

      string sName = "All";

      if (!string.IsNullOrWhiteSpace(DTStart))
      {
        sName = DTStart;

        if (!string.IsNullOrWhiteSpace(DTEnd))
        {
          sName = sName + " - " + DTEnd;
        }
      }
      else if (!string.IsNullOrWhiteSpace(DTEnd))
      {
        sName = DTEnd;
      }
      else if (!string.IsNullOrWhiteSpace(Sender))
      {
        sName = "Sender: " + Sender;
      }
      else if (!string.IsNullOrWhiteSpace(IdStr))
      {
        sName = "ID: " + IdStr;
      }

      xmlWriter.WriteElementString("name", sName);

      History.GetPlaybackKMLForDEList(xmlWriter, items);

      xmlWriter.WriteEndElement();
      xmlWriter.WriteEndDocument();
      xmlWriter.Flush();
      xmlWriter.Close();

      WebOperationContext.Current.OutgoingResponse.ContentType = "application/vnd.google-earth.kml+xml";
      return XElement.Parse(sb.ToString());
    }

    /// <summary>
    /// Endpoint to return GeoRSS of all of the DE messages in the Message history table
    /// </summary>
    /// <returns>GeoRSS representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "GeoRSS/All", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public Atom10FeedFormatter GetGeoRSSFeedAll()
    {
      List<XElement> items = null;
      items = History.GetAllDE();

      SyndicationFeed feed = new SyndicationFeed();
      XmlQualifiedName n = new XmlQualifiedName(ICNETSOAConstants.ICNETQualifiedName, "http://www.w3.org/2000/xmlns/");
      String icnetNs = ICNETSOAConstants.ICNETNamespace;
      feed.AttributeExtensions.Add(n, icnetNs);

      List<SyndicationItem> synItems = null;

      synItems = History.GetGeoRSSForDEList(items);
      feed.Title = new TextSyndicationContent("IC.NET History DE Feed: ");

      feed.Items = synItems;
      feed.LastUpdatedTime = this.GetMostRecentSyndicationItemTime(synItems);
      feed.AddSelfLink(WebOperationContext.Current.IncomingRequest.GetRequestUri());
      WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
      return feed.GetAtom10Formatter();
    }

    /// <summary>
    /// Endpoint to return GeoRSS of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or DE DateTime Sent
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTSent">DateTime Sent</param>
    /// <returns>GeoRSS representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "GeoRSS/DE?Id={IdStr}&Sender={Sender}&Sent={DTSent}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public Atom10FeedFormatter GetGeoRSSFeedByDE(string IdStr, string Sender, string DTSent = "")
    {
      List<XElement> items = null;
      items = History.GetDE(IdStr, Sender, DTSent);

      SyndicationFeed feed = new SyndicationFeed();
      XmlQualifiedName n = new XmlQualifiedName(ICNETSOAConstants.ICNETQualifiedName, "http://www.w3.org/2000/xmlns/");
      feed.AttributeExtensions.Add(n, ICNETSOAConstants.ICNETNamespace);

      n = new XmlQualifiedName(EDXLConstants.GeoRSSPrefix, "http://www.w3.org/2000/xmlns/");
      feed.AttributeExtensions.Add(n, EDXLConstants.GeoRSSNamespace);

      List<SyndicationItem> synItems = null;

      synItems = History.GetGeoRSSForDEList(items);
      feed.Title = new TextSyndicationContent("IC.NET History DE Feed: ");

      feed.Items = synItems;
      feed.LastUpdatedTime = this.GetMostRecentSyndicationItemTime(synItems);
      feed.AddSelfLink(WebOperationContext.Current.IncomingRequest.GetRequestUri());
      WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
      return feed.GetAtom10Formatter();
    }

    /// <summary>
    /// Endpoint to return GeoRSS of the DE messages in the Message history table that match on 
    /// time range
    /// </summary>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>GeoRSS representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "GeoRSS/Time?Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public Atom10FeedFormatter GetGeoRSSFeedByTime(string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByTime(DTStart, DTEnd);

      SyndicationFeed feed = new SyndicationFeed();
      XmlQualifiedName n = new XmlQualifiedName(ICNETSOAConstants.ICNETQualifiedName, "http://www.w3.org/2000/xmlns/");
      String icnetNs = ICNETSOAConstants.ICNETNamespace;
      feed.AttributeExtensions.Add(n, icnetNs);

      List<SyndicationItem> synItems = null;

      synItems = History.GetGeoRSSForDEList(items);
      feed.Title = new TextSyndicationContent("IC.NET History DE Feed: ");

      feed.Items = synItems;
      feed.LastUpdatedTime = this.GetMostRecentSyndicationItemTime(synItems);
      feed.AddSelfLink(WebOperationContext.Current.IncomingRequest.GetRequestUri());
      WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
      return feed.GetAtom10Formatter();
    }

    /// <summary>
    /// Endpoint to return GeoRSS of the DE messages in the Message history table that match on 
    /// Distribution Id, Sender Id, and/or time range
    /// </summary>
    /// <param name="IdStr">Distribution Id</param>
    /// <param name="Sender">Sender Id</param>
    /// <param name="DTStart">Start time</param>
    /// <param name="DTEnd">End Time</param>
    /// <returns>GeoRSS representation of DE messages in the Message history table entries</returns>
    [WebGet(UriTemplate = "GeoRSS/DETime?Id={IdStr}&Sender={Sender}&Start={DTStart}&End={DTEnd}", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare), OperationContract]
    public Atom10FeedFormatter GetGeoRSSFeedByDEAndTime(string IdStr, string Sender, string DTStart, string DTEnd)
    {
      List<XElement> items = null;
      items = History.GetDEByDEAndTime(IdStr, Sender, DTStart, DTEnd);

      SyndicationFeed feed = new SyndicationFeed();
      XmlQualifiedName n = new XmlQualifiedName(ICNETSOAConstants.ICNETQualifiedName, "http://www.w3.org/2000/xmlns/");
      String icnetNs = ICNETSOAConstants.ICNETNamespace;
      feed.AttributeExtensions.Add(n, icnetNs);

      List<SyndicationItem> synItems = null;

      synItems = History.GetGeoRSSForDEList(items);
      feed.Title = new TextSyndicationContent("IC.NET History DE Feed: ");

      feed.Items = synItems;
      feed.LastUpdatedTime = this.GetMostRecentSyndicationItemTime(synItems);
      feed.AddSelfLink(WebOperationContext.Current.IncomingRequest.GetRequestUri());
      WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
      return feed.GetAtom10Formatter();
    }

    /// <summary>
    /// Iterates thorugh a list of syndication items to find the date of the most recent one. 
    /// </summary>
    /// <param name="items">The list to be iterated through. </param>
    /// <returns>The date and time of the most recent item.</returns>
    private DateTimeOffset GetMostRecentSyndicationItemTime(List<SyndicationItem> items)
    {
      if (items.Count == 0)
      {
        return DateTimeOffset.Now;
      }

      DateTimeOffset mostRecentTime = items[0].LastUpdatedTime;
      foreach (SyndicationItem item in items)
      {
        if (item.LastUpdatedTime.CompareTo(mostRecentTime) < 0)
        {
          mostRecentTime = item.LastUpdatedTime;
        }
      }

      return mostRecentTime;
    }
  }
}
